from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required


import datetime

from cashflow.models import *
from cashflow.forms import *


@login_required
def OverviewView(request):
    
    date_from = (datetime.date.today() - datetime.timedelta(90)) 
    transactions = Transaction.objects.filter(user=request.user).filter(date__gte=date_from).order_by('date')
    
    cash = {'summary':0,'income':0,'expense':0}
    history_items = []
    balance = 0
    for t in transactions:
        account_name = 'No Account'
        if t.account :
            account_name = t.account.name        
        item = {'description':t.description, 'datetime':t.date, 'category': t.category,
              'income':'', 'expense':'', 'balance':'', 'account':account_name}
        if t.amount >= 0 :
            item['income'] = t.amount
            cash['income'] += t.amount
        else:
            item['expense'] = 0 - t.amount 
            cash['expense'] += t.amount 
        balance += t.amount
        item['balance'] = balance
        history_items.append(item)
    cash['summary'] = cash['income'] - cash['expense']
  
    accounts = request.user.account_set.all()
    summary_balance = 0
    for account in accounts :
        summary_balance += account.balance
    #transaction_form = TransactionForm(user=request.user)
    return render(request,'cashflow/overview.html',{
        'request' : request,
        'accounts' : accounts,
        'summary_balance' : summary_balance,
        'history' : history_items,
        'cash' : cash,
        }) 


#
# Account
#      
@login_required
def AccountView(request):
    accounts = Account.objects.filter(user=request.user).order_by('updated')
    print 'account'
    return render(request,'cashflow/account.html',{'accounts' : accounts,})
    
@login_required
def AccountAdd(request):
    if request.method == 'POST':
        form = AccountForm(request.POST)
        if form.is_valid():
            new_acc = form.save(commit=False)
            new_acc.user = request.user
            new_acc.save()
            return HttpResponseRedirect(reverse("account"))
    else:
        form = AccountForm()
    return render(request,'cashflow/account_add.html',{'request' : request,'form' : form})

@login_required
def AccountEdit(request,id):
    account = get_object_or_404(Account, id=id, user=request.user)
    if request.method == 'POST':
        form = AccountForm(request.POST, instance=account)
        if form.is_valid():
            account = form.save()
            return HttpResponseRedirect(reverse("account"))
    else:
        form = AccountForm(instance=account)
    return render(request,'cashflow/account_edit.html',{'request' : request,'form' : form})
    
# TODO :
# - add delete feature
# - move object relate to this account to default account
@login_required
def AccountDelete(request,id):
    account = get_object_or_404(Account, id=id, user=request.user)
    account.delete()
    return HttpResponseRedirect(reverse("account"))

    
          
#
# Category
#      
@login_required
def CategoryView(request, name = None):
    categorys = Category.objects.filter(user=request.user).order_by('name')
    return render(request,'cashflow/category.html',{
      'request' : request,
      'categorys' : categorys,
      }) 

@login_required
def CategoryAdd(request):
    if request.method == 'POST':
        form = CategoryForm(request.POST)
        if form.is_valid():
            new = form.save(commit=False)
            new.user = request.user
            new.save()
            return HttpResponseRedirect(reverse("category"))
    else:
        form = CategoryForm()
    return render(request,'cashflow/category_add.html',{'request' : request,'form' : form})
 

@login_required
def CategoryEdit(request,id):
    category = get_object_or_404(Category, id=id, user=request.user)
    if request.method == 'POST':
        form = CategoryForm(request.POST, instance=category)
        if form.is_valid():
            category = form.save()
            return HttpResponseRedirect(reverse("category"))
    else:
        form = CategoryForm(instance=category)
    return render(request,'cashflow/category_edit.html',{'request' : request,'form' : form})

# TODO :
# - add delete feature
# - move object relate to this category to default category    
@login_required
def CategoryDelete(request,id):
    category = get_object_or_404(Category, id=id, user=request.user)
    # cannot delete for now because you need to assign transaction to another category before delete
    #category.delete()
    return HttpResponseRedirect(reverse("category"))

     
#
# Transaction
#    
@login_required
def TransactionView(request, aid = None, cid = None):

    accountName = None
    categoryName = None
    queryset = Transaction.objects.filter(user=request.user).order_by('date')

    if aid :
        account = get_object_or_404(Account, id=aid, user=request.user)
        queryset = queryset.filter(account=account)
        accountName = account.name

    if cid :
        category = get_object_or_404(Category, id=cid, user=request.user)
        queryset = queryset.filter(category=category)
        categoryName = category.name


      
    date_from = None
    date_to = None
    if request.method == 'POST':
        history_form = FilterHistoryForm(request.POST)
        if history_form.is_valid():
            if history_form.cleaned_data['date_from']:
                date_from = history_form.cleaned_data['date_from']
                queryset = queryset.filter(date__gte=date_from)
            if history_form.cleaned_data['date_to']:
                date_to = history_form.cleaned_data['date_to']
                queryset = queryset.filter(date__lte=history_form.cleaned_data['date_to'])
            if history_form.cleaned_data['keywords']:
                queryset = queryset.filter(description__contains=history_form.cleaned_data['keywords'])
    else:
        date_from = (datetime.date.today() - datetime.timedelta(30)).isoformat()
        history_form = FilterHistoryForm(initial={"date_from":date_from})
        queryset = queryset.filter(date__gte=date_from)
    
    history_items = []
    balance = 0
    for t in queryset:
        account_name = 'No Account'
        if t.account :
            account_name = t.account.name
            
        item = {'description':t.description, 'datetime':t.date, 'category': t.category,
                'income':'', 'expense':'', 'balance':'', 'account':account_name}
        if t.amount >= 0 :
            item['income'] = t.amount
        else:
            item['expense'] = 0 - t.amount 
        balance += t.amount
        item['balance'] = balance
        history_items.append(item)
        
    accounts = request.user.account_set.all()
    summary_balance = 0
    for account in accounts :
        summary_balance += account.balance
    transaction_form = TransactionForm(user=request.user)
    return render(request,'cashflow/transaction.html',{
      'request' : request,
      'accounts' : accounts,
      'summary_balance' : summary_balance,
      'accountName' : accountName,
      'categoryName' : categoryName,
      'history' : history_items,
      'history_form' : history_form,
      'transaction_form' : transaction_form,
      'date_from' : date_from,
      'date_to' : date_to,
      }) 
    
    
@login_required
def TransactionAdd(request):
    if request.method == 'POST':
        form = TransactionForm(request.POST,user=request.user)
        if form.is_valid():
            account = get_object_or_404(Account, name=form.cleaned_data['account'], user=request.user)
            
            amount = form.cleaned_data['amount']
            category = get_object_or_404(Category, name=form.cleaned_data['category'], user=request.user)
            
            if category.type == 1:
                amount = 0-amount
              
            account.add_transaction(name=form.cleaned_data['name'],
                        amount=amount,
                        category=category,
                        date=form.cleaned_data['date'],
                        description=form.cleaned_data['description'])
                        
            #return HttpResponseRedirect(reverse("transaction-by-account", args=[account.id]))
            return HttpResponseRedirect(request.META["HTTP_REFERER"])
    else:
        form = TransactionForm(user=request.user)
    return render(request,'cashflow/transaction_add.html',{'request' : request,'form' : form})

#
# Bill
#    
@login_required
def BillView(request):   
    date_from = datetime.datetime.now()
    date_to = datetime.datetime.now() + datetime.timedelta(days=30)
    bills = Bill.objects.filter(user=request.user).filter(start__lte=date_to)
    #bills = Bill.objects.filter(user=request.user).filter(start__lte=date_to).filter(end__gte=date_from)
    events = []
    
    for bill in bills :
        t_date_from = date_from
        if bill.last < date_from:
            t_date_from = bill.last
        
        occurences = bill.get_occurrences(t_date_from,date_to)
        #print "date : ",t_date_from," - ",date_to," : ",occurences
        for occdate in occurences :
            alert = False
            if occdate < datetime.datetime.today() :
                alert = True
            paid = False
            if occdate <= bill.last :
                paid = True
            event = {'date':occdate,
                      'id':bill.id,
                      'name':bill.name,
                      'amount':bill.amount,
                      'category':bill.category,
                      'account':bill.account,
                      'alert':alert,
                      'paid':paid}
            events.append(event)
    
    form = TransactionForm(user=request.user)
    accounts = request.user.account_set.all()
    categorys = request.user.category_set.all()
    summary_balance = 0
    for account in accounts :
        summary_balance += account.balance    
    return render(request,'cashflow/bill.html',{
      'request' : request,
      'accounts' : accounts,
      'categorys' : categorys,
      'summary_balance' : summary_balance,      
      'form':form,
      'date_from':date_from,
      'date_to':date_to,
      'bills' : events,
      })
      
@login_required
def BillViewBalance(request): 
    from operator import itemgetter
    date_from = datetime.datetime.now()
    date_to = datetime.datetime.now() + datetime.timedelta(days=365)
    bills = Bill.objects.filter(user=request.user).filter(start__lte=date_to)
    events = []
   
    for bill in bills :
        occurences = bill.get_occurrences(date_from,date_to)
        for occdate in occurences :
            amount = bill.amount
            if bill.category.name == 'expense':
                amount = 0 - amount
            event = {'date':occdate,
                      'id':bill.id,
                      'name':bill.name,
                      'amount':amount,
                      'category':bill.category,
                      'account':bill.account}
            events.append(event)
    
    events = sorted(events, key=itemgetter('date'))
    return render(request,'cashflow/bill_balance.html',{
      'request' : request,
      'bills' : events,
      })      
      
@login_required
def BillManage(request):
    bills = Bill.objects.filter(user=request.user)
  
    return render(request,'cashflow/bill_manage.html',{'request' : request,'bills' : bills,})
     
@login_required
def BillAdd(request):
    if request.method == 'POST':
        #print request.POST['rimonthlytype']
        name = request.POST['name']
        description = request.POST['description']
        name = request.POST['name']
        date = datetime.datetime.strptime(request.POST['date'],'%m/%d/%Y')
        account = get_object_or_404(Account, id=request.POST['account'], user=request.user)
        amount = float(request.POST['amount'])
        category = get_object_or_404(Category, id=request.POST['category'], user=request.user)
        if category.type == 1:
            amount = 0-amount      
        
        frequency = request.POST['freq']
        params = ''
        params = params + 'interval:' + request.POST['interval'] + ';'
        
        if frequency == 'weekly' :
            params = params + 'byweekday:' 
            for day in  request.POST.getlist('byweekday'):
                params = params + day + ','
            params = params[:-1] + ';'
          
        if frequency == 'monthly' : 
            if request.POST['rimonthlytype'] == 'DAYOFMONTH':
                # 1 - 31
                params = params + 'bymonthday:' + request.POST['bymonthday'] + ';'
            
            if request.POST['rimonthlytype'] == 'WEEKDAYOFMONTH':
                params = params + 'byweekday:'
                params = params + request.POST['weekdayofmonth']
                params = params + '(' + request.POST['weekdayofmonthindex'] + ')'+ ';'
        
        if frequency == 'yearly' :       
            if request.POST['riyearlyType'] == 'DAYOFMONTH':
                params = params + 'bymonth:'
                params = params + request.POST['yearlybymonth']+';'
                params = params + 'bymonthday:'
                params = params + request.POST['yearlybymonthday']+';'
              
            if request.POST['riyearlyType'] == 'WEEKDAYOFMONTH':
                params = params + 'bymonth:'
                params = params + request.POST['yearlyweekdaymonth']+';'
                params = params + 'byweekday:'
                params = params + request.POST['yearlyweekday']
                params = params + '(' + request.POST['yearlyweekdayofmonth'] + ')'+ ';'        

        
        start = datetime.datetime.strptime(request.POST['startdate'],'%m/%d/%Y')
        
        if request.POST['end'] == 'BYOCCURRENCES':
            params = params + 'count:'
            params = params + request.POST['count']+';'
        
        end = None
        if request.POST['end'] == 'BYENDDATE':
            end = datetime.datetime.strptime(request.POST['enddate'],'%m/%d/%Y')
        
        print '---------' + params
        print start
        
        
        
        bill = Bill(user=request.user,
                    account=account,
                    date=date,
                    name=name,
                    amount=amount, 
                    category=category,
                    description=description,
                    start = start,
                    end = end,
                    last = start)
        bill.save()    
        bill.set_rule(frequency,params)
        
        
        return HttpResponseRedirect(request.META["HTTP_REFERER"])
    else:
        form = TransactionForm(user=request.user)
    return render(request,'cashflow/bill_add.html',{'request' : request,'form' : form})
      
@login_required
def BillPay(request):
    if request.method == 'POST':
        form = TransactionForm(request.POST,user=request.user)
        if form.is_valid():
            account = get_object_or_404(Account, name=form.cleaned_data['account'], user=request.user)
            
            amount = form.cleaned_data['amount']
            category = get_object_or_404(Category, name=form.cleaned_data['category'], user=request.user)
            
            if category.type == 1:
                amount = 0-amount
              
            account.add_transaction(name=form.cleaned_data['name'],
                        amount=amount,
                        category=category,
                        date=form.cleaned_data['date'],
                        tags=form.cleaned_data['tags'],
                        description=form.cleaned_data['description'])
                        
            bill = get_object_or_404(Bill, id=request.POST['billid'], user=request.user)
            bill.last = start = datetime.datetime.strptime(request.POST['billdate'],'%m/%d/%Y')
            bill.save()
            return HttpResponseRedirect(request.META["HTTP_REFERER"])
    else:
        form = TransactionForm(user=request.user)
    return render(request,'cashflow/transaction_add.html',{'request' : request,'form' : form})

    
#
# Bill
#    
@login_required
def BudgetView(request):   
    nextmonth = datetime.date.today().month%12 + 1
    today = datetime.date.today().day
    endday = (datetime.date.today().replace(day=1,month=nextmonth)-datetime.timedelta(days=1)).day
    today_percent = int((today*100.00)/endday)
    
    try:
        budgets = Budget.objects.filter(user=request.user).order_by('account')
    except ObjectDoesNotExist:
        return HttpResponseRedirect(reverse('budget_add'))

    budgets_summary = []
    for budget in budgets :
        amount_use = budget.get_monthusage()
        amount_estimate = budget.estimate
        progress_percent = int(amount_use / amount_estimate * 100)
          
        if progress_percent > 100 :
            color_class = 'alert'
        elif progress_percent > today_percent :
            color_class = 'warning'
        else :
            color_class = 'ok'
          
        if progress_percent > 100:
            progress_percent = 100         
              
        budgets_summary.append({
                  'account':budget.account,
                  'category':budget.category,
                  'amount_estimate':amount_estimate,
                  'amount_use':amount_use,
                  'amount_left':amount_estimate - amount_use,
                  'progress_percent':progress_percent,
                  'color_class':color_class
                  })
           
    return render(request,'cashflow/budget.html',{
      'request' : request,
      'budgets_summary' : budgets_summary,
      'today' : today,
      'endday' : endday,
      'today_percent' : today_percent,
      })    
      
@login_required
def BudgetAdd(request):
    if request.method == 'POST':
        form = BudgetForm(request.POST)
        if form.is_valid():
            new = form.save(commit=False)
            new.user = request.user
            new.save()
            return HttpResponseRedirect(reverse("budget"))
    else:
        form = BudgetForm()
    return render(request,'cashflow/budget_add.html',{'request' : request,'form' : form})      
#================================================================


@login_required
def move_money(request, name):
    account = get_object_or_404(Account, name=name, user=request.user)
    if request.method == 'POST':
        form = MoveMoneyForm(request.POST, from_account=account, user=request.user)
        if form.is_valid():
            account.move_money(to_account=form.cleaned_data['account'],
                               amount=form.cleaned_data['amount'],
                               category="Move Money",
                               tags=form.cleaned_data['tags'],
                               description=form.cleaned_data['description'])
            return HttpResponseRedirect(reverse("account-details", args=[account.name]))
    else:
        form = MoveMoneyForm(from_account=account, user=request.user)
    return render(request,'cashflow/transaction_move.html',{'form' : form})



